package com.app.web.base.service;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.app.web.base.controller.LoginBean;
import com.app.web.base.model.Resource;
import com.app.web.base.model.Role;
import com.app.web.base.model.RoleResource;
import com.app.web.base.model.UserResource;
import com.app.web.base.vo.RoleResourceVO;
import com.app.web.base.vo.UserResourceVO;

/**
 * Project: erp<br>
 * Description: 资源管理Service，容器单例<br>
 * Copyright (c) 2012<br>
 * All Rights Reserved.<br>
 * @author <a href="mailto:gly420@163.com">GuanLuYong</a><br>
 */
@Service @Scope("singleton")
public class ResourceService extends BaseService<Resource> implements Serializable {
	private static final long serialVersionUID = 1L;
	@javax.annotation.Resource private RoleService roleService;
	@javax.annotation.Resource private LoginBean loginBean;
	/**
	 * 查询资源列表，构建成一颗树
	 * @param root
	 */
	@SuppressWarnings("unchecked")
	public void buildTree(TreeNode root, Map<String, Object> query) {
		Long parentId;
		if(root.getData() instanceof String) {	//第一次
			parentId = 0L;
		} else {
			parentId = ((Resource) root.getData()).getId();
		}
		StringBuilder sql = new StringBuilder("SELECT r FROM Resource r WHERE r.parentId=:parentId ");
		Object code = query.get("code");
		if(code != null && !"".equals(code.toString())) {
			sql.append("AND r.code LIKE '" + code.toString() + "%'");
		}
		Object type = query.get("type");
		if(type != null && !"".equals(type.toString())) {
			sql.append("AND r.type = '" + type.toString() + "' ");
		}
		sql.append("ORDER BY r.code");
		List<Resource> reses = em.createQuery(sql.toString()).setParameter("parentId", parentId).getResultList();
		for(Resource res : reses) {
			buildTree(new DefaultTreeNode(res, root), query);
		}
	}
	/**
	 * 根据资源类型查找资源，没有限定类型，查找所有
	 * @param type 资源类型
	 * @return 资源集合
	 */
	@SuppressWarnings("unchecked")
	public List<Resource> getResourcesByParentId(Long parentId) {
		String sql = "SELECT r FROM Resource r WHERE r.parentId=:parentId ORDER BY r.code";
		return em.createQuery(sql).setParameter("parentId", parentId).getResultList();
	}
	/**
	 * 查找资源所属的角色及权限
	 * @param resId
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<RoleResourceVO> getRolesByResId(Long resId) {
		String sql = "SELECT NEW com.app.web.base.vo.RoleResourceVO(rr) " +
				"FROM RoleResource rr, Role ro, Resource re " +
				"WHERE rr.res=re AND rr.role=ro AND re.id=:resId AND ro.status=1 AND rr.status=1 " +
				"ORDER BY ro.code";
		return em.createQuery(sql).setParameter("resId", resId).getResultList();
	}
	public List<Role> getAllRoles() {
		return roleService.getAllRoles();
	}
	@Transactional(propagation = Propagation.REQUIRED)
	public void communicateRoleRes(final List<RoleResourceVO> list, final Resource res) {
		String sql = "SELECT rr FROM RoleResource rr WHERE rr.res.id = " + res.getId();
		List<RoleResource> rs = em.createQuery(sql).getResultList();
		for(RoleResourceVO r : list) {
			RoleResource r1 = null;
			for(RoleResource rr : rs) {
				if(rr.getRole().getId().compareTo(r.getId()) == 0 
						&& rr.getRes().getId().compareTo(res.getId()) == 0) {
					r1 = rr;
					break;
				}
			}
			if(r.getPermission().isNullPermission()) {
				if(r1 != null) {
					r1.setStatus(1024l);
					r1.setModBy(loginBean.getUser().getAccount());
					r1.setModDate(new Date());
					r1.setPermission(r.getPermission().toLong());
					em.merge(r1);
				}
			} else {
				if(r1 != null) {
					r1.setModBy(loginBean.getUser().getAccount());
					r1.setModDate(new Date());
					r1.setPermission(r.getPermission().toLong());
					r1.setStatus(1l);
					em.merge(r1);
				} else {
					r1 = new RoleResource();
					r1.setAddBy(loginBean.getUser().getAccount());
					r1.setAddDate(new Date());
					r1.setModBy(loginBean.getUser().getAccount());
					r1.setModDate(new Date());
					r1.setPermission(r.getPermission().toLong());
					r1.setRes(res);
					r1.setRole(r.getRole());
					r1.setStatus(1l);
//					r1.setId(systemUtils.generatorId());
					em.persist(r1);
				}
			}
		}
		
		for(RoleResource rr : rs) {
			boolean f = false;
			for(RoleResourceVO r : list) {
				if(r.getRole().getId().compareTo(rr.getRole().getId()) == 0 && 
						res.getId().compareTo(rr.getRes().getId()) == 0) {
					f = true;
					break;
				}
			}
			if(!f) {
				rr.setStatus(1024l);
				rr.setModBy(loginBean.getUser().getAccount());
				rr.setModDate(new Date());
				em.merge(rr);
			}
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void update(Resource t) throws Exception {
		super.update(t);
	}
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void insert(Resource t) throws Exception {
		super.insert(t);
	}
	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void delete(Resource t) throws Exception {
		super.delete(t);
	}
	
	public List<UserResourceVO> getUsersByResId(final Long id) {
		String sql = "SELECT NEW com.app.web.base.vo.UserResourceVO(ur) " +
				"FROM UserResource ur WHERE ur.status=1 AND ur.user.status=1 AND ur.res.id=:id " +
				"ORDER BY ur.user.code";
		return em.createQuery(sql).setParameter("id", id).getResultList();
	}
	@Transactional
	public void communicateResUsers(final List<UserResourceVO> urvs, final Resource res) {
		String sql = "SELECT ur FROM UserResource ur WHERE ur.res.id = :id";
		List<UserResource> urs = em.createQuery(sql).setParameter("id", res.getId()).getResultList();
		Date date = new Date();
		String account = loginBean.getUser().getAccount();
		
		for(UserResourceVO urv : urvs) {
			UserResource ur = null;
			for(UserResource ur1 : urs) {
				if(urv.getUser().getId().compareTo(ur1.getUser().getId()) == 0 && 
						res.getId().compareTo(ur1.getRes().getId()) == 0) {
					ur = ur1;
					break;
				}
			}
			if(urv.getPermission().isNullPermission()) {
				if(ur != null) {
					ur.setStatus(1024L);
					ur.setModBy(account);
					ur.setModDate(date);
					ur.setPermission(urv.getPermission().toLong());
					em.merge(ur);
				}
			} else {
				if(ur != null) {
					ur.setStatus(1L);
					ur.setModBy(account);
					ur.setModDate(date);
					ur.setPermission(urv.getPermission().toLong());
					em.merge(ur);
				} else {
					ur = new UserResource();
					ur.setAddBy(account);
					ur.setAddDate(date);
					ur.setModBy(account);
					ur.setModDate(date);
					ur.setPermission(urv.getPermission().toLong());
					ur.setRes(res);
					ur.setUser(urv.getUser());
					ur.setStatus(1L);
//					ur.setId(systemUtils.generatorId());
					em.persist(ur);
				}
			}
		}
	}
	
	public RoleService getRoleService() {
		return roleService;
	}
	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}
}
